// Copyright (c) 2022 by Duguang.IO Inc. All Rights Reserved.
// Author: Ethan Liu
// Date: 2022-05-05 12:43:18

package engine

import (
	"net/url"
	"strings"

	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/mount"
)

// 容器配置转换，可移植配置
func toConfig(spec *Spec, host string) *container.Config {
	if spec.Labels != nil {
		spec.Labels["creator"] = "jianmu"
	} else {
		spec.Labels = map[string]string{"creator": "jianmu"}
	}
	config := &container.Config{
		Image:        spec.Image,
		Labels:       spec.Labels,
		WorkingDir:   spec.WorkingDir,
		User:         spec.User,
		AttachStdin:  false,
		AttachStdout: true,
		AttachStderr: true,
		Tty:          false,
		OpenStdin:    false,
		StdinOnce:    false,
		ArgsEscaped:  false,
	}

	if len(spec.Envs) != 0 {
		config.Env = toEnv(spec.Envs)
	}
	// 添加DOCKER_HOST环境变量
	config.Env = append(config.Env, "DOCKER_HOST="+host)
	for _, sec := range spec.Secrets {
		config.Env = append(config.Env, sec.Env+"="+string(sec.Data))
	}

	if len(spec.Entrypoint) != 0 {
		config.Entrypoint = spec.Entrypoint
	}
	if len(spec.Command) != 0 {
		config.Cmd = spec.Command
	}
	return config
}

// 容器主机配置，不可移植依赖主机类型的配置
func toHostConfig(spec *Spec, host, networkMode string) *container.HostConfig {
	config := &container.HostConfig{
		NetworkMode: container.NetworkMode(networkMode),
		LogConfig: container.LogConfig{
			Type: "json-file",
		},
	}

	if len(spec.DNS) > 0 {
		config.DNS = spec.DNS
	}
	if len(spec.DNSSearch) > 0 {
		config.DNSSearch = spec.DNSSearch
	}
	if len(spec.ExtraHosts) > 0 {
		config.ExtraHosts = spec.ExtraHosts
	}

	if !isUnlimited(spec) {
		config.Resources = container.Resources{
			CPUPeriod:  spec.CPUPeriod,
			CPUQuota:   spec.CPUQuota,
			CpusetCpus: strings.Join(spec.CPUSet, ","),
			CPUShares:  spec.CPUShares,
			Memory:     spec.MemLimit,
			MemorySwap: spec.MemSwapLimit,
			NanoCPUs:   int64(spec.CPUS * 1000000000),
		}
	}

	if len(spec.Volumes) != 0 {
		config.Mounts = toVolumeMounts(spec)
	}

	// 解析host
	u, err := url.Parse(host)
	if err != nil {
		return config
	}

	// 如果docker host使用unix sock文件则挂载宿主机sock文件
	if u.Scheme == "unix" {
		config.Mounts = append(config.Mounts, mount.Mount{
			Type:   mount.TypeBind,
			Target: u.Path,
			Source: u.Path,
		})
	}
	return config
}

// 创建VolumeMounts
func toVolumeMounts(spec *Spec) []mount.Mount {
	var mounts []mount.Mount
	for _, mount := range spec.Volumes {
		mounts = append(mounts, toMount(mount.Source, mount.Target))
	}
	if len(mounts) == 0 {
		return nil
	}
	return mounts
}

// 创建Mount
func toMount(source string, target string) mount.Mount {
	to := mount.Mount{
		Target: target,
		Source: source,
		Type:   mount.TypeVolume,
	}
	return to
}

// 创建环境变量列表
func toEnv(env map[string]string) []string {
	var envs []string
	for k, v := range env {
		envs = append(envs, k+"="+v)
	}
	return envs
}

// returns true if the container has no resource limits.
func isUnlimited(res *Spec) bool {
	return len(res.CPUSet) == 0 &&
		res.CPUPeriod == 0 &&
		res.CPUQuota == 0 &&
		res.CPUShares == 0 &&
		res.MemLimit == 0 &&
		res.MemSwapLimit == 0
}
